// -----------------------------
// Author: 		Dhaenens Gert	
// Creation: 	2/12/2015 10:46:27 PM				
// -----------------------------

#include "CWindow.h"

namespace Flow
{

	CWindow::CWindow()
		: m_hWindow(NULL)
		, m_IsAlive(false)
		, m_IsVisible(false)
		, m_Width(0)
		, m_Height(0)
	{
	}

	CWindow::~CWindow()
	{
	}

	void CWindow::Release()
	{
		delete this;
	}

	Bool CWindow::Initialize(const GameConfig& config)
	{
		tstring tCaption = tstring(config.Caption.begin(), config.Caption.end());

		WNDCLASS wndClass = {};
		wndClass.hbrBackground = (HBRUSH)COLOR_WINDOW + 1;
		wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
		wndClass.hInstance = GetModuleHandle(NULL);
		wndClass.lpfnWndProc = CWindow::WndProcWrapper;
		wndClass.lpszClassName = tCaption.c_str();

		if (!RegisterClass(&wndClass))
			return false;

		DWORD dwStyle = WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_CAPTION;
		RECT wndRect = {};
		wndRect.left = (GetSystemMetrics(SM_CXSCREEN) - config.Width) / 2;
		wndRect.top = (GetSystemMetrics(SM_CYSCREEN) - config.Height) / 2;
		wndRect.right = wndRect.left + config.Width;
		wndRect.bottom = wndRect.top + config.Height;
		AdjustWindowRect(&wndRect, dwStyle, FALSE);

		m_hWindow = CreateWindow(wndClass.lpszClassName, tCaption.c_str(), dwStyle, wndRect.left, wndRect.top,
			wndRect.right - wndRect.left, wndRect.bottom - wndRect.top, NULL, NULL, wndClass.hInstance, this);
		if (!m_hWindow)
			return false;

		ShowWindow(m_hWindow, SW_SHOW);
		UpdateWindow(m_hWindow);

		m_Width = config.Width;
		m_Height = config.Height;
		m_IsAlive = true;

		return true;
	}
	void CWindow::Close()
	{
		SendMessage(m_hWindow, WM_DESTROY, 0, 0);
	}

	Bool CWindow::HandleMessages(ProcessOption::Enum type) const
	{
		Bool bMessageFound = false;

		do 
		{
			MSG msg = {};
			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);

				bMessageFound = true;
			}
			else
				bMessageFound = false;
		} 
		while (bMessageFound && (type != ProcessOption::ProcessOne));
		
		return bMessageFound;
	}

	Bool CWindow::IsAlive() const
	{
		return m_IsAlive;
	}
	Bool CWindow::IsVisible() const
	{
		return m_IsVisible;
	}

	HWND CWindow::GetHandle() const
	{
		return m_hWindow;
	}
	UInt32 CWindow::GetWidth() const
	{
		return m_Width;
	}
	UInt32 CWindow::GetHeight() const
	{
		return m_Height;
	}

	LRESULT WINAPI CWindow::WndProcWrapper(HWND hWindow, UINT uMessage, WPARAM wParam, LPARAM lParam)
	{
		CWindow* lpWindow = nullptr;
		if (uMessage == WM_NCCREATE)
		{
			CREATESTRUCT* lpStruct = reinterpret_cast<CREATESTRUCT*>(lParam);
			lpWindow = reinterpret_cast<CWindow*>(lpStruct->lpCreateParams);
			SetWindowLongPtr(hWindow, GWLP_USERDATA, (LONG_PTR)lpWindow);
		}
		else
			lpWindow = reinterpret_cast<CWindow*>(GetWindowLongPtr(hWindow, GWLP_USERDATA));

		if (lpWindow)
			return lpWindow->WndProc(hWindow, uMessage, wParam, lParam);
		return DefWindowProc(hWindow, uMessage, wParam, lParam);
	}
	LRESULT CWindow::WndProc(HWND hWindow, UINT uMessage, WPARAM wParam, LPARAM lParam)
	{
		switch (uMessage)
		{
			case WM_DESTROY:
			{
				m_IsAlive = false;
				return 0;
			}
			case WM_ACTIVATE:
			{
				if (wParam == WA_INACTIVE)
					m_IsVisible = false;
				else
					m_IsVisible = true;
				return 0;
			}
		}

		return DefWindowProc(hWindow, uMessage, wParam, lParam);
	}

}